// #ifdef APP-ANDROID
import Choreographer from "android.view.Choreographer"; // Android 帧同步器，提供垂直同步信号
import FrameCallback from "android.view.Choreographer.FrameCallback"; // 帧回调接口
import Long from "kotlin.Long"; // Kotlin Long 类型
// #endif

/**
 * 缓动函数类型定义
 */
export type EasingFunction = (progress: number) => number;

/**
 * 动画属性配置
 */
export type AnimationAttribute = {
	/** 起始值 */
	fromValue: string;
	/** 结束值 */
	toValue: string;
	/** 单位 (px, %, deg等) */
	unit: string;
	/** 当前值 */
	currentValue: string;
	/** 当前进度 (0-1) */
	progress: number;
	/** 属性名称 */
	propertyName: string;
};

/**
 * 动画配置选项
 */
export type AnimationOptions = {
	/** 动画持续时间(毫秒) */
	duration?: number;
	/** 循环次数 (-1为无限循环) */
	loop?: number;
	/** 是否往返播放 */
	alternate?: boolean;
	/** 是否按属性顺序依次执行动画 */
	sequential?: boolean;
	/** 缓动函数名称 */
	timingFunction?: string;
	/** 自定义贝塞尔曲线参数 */
	bezier?: number[];
	/** 动画完成回调 */
	complete?: () => void;
	/** 动画开始回调 */
	start?: () => void;
	/** 每帧回调 */
	frame?: (progress: number) => void;
};

// 贝塞尔曲线计算常量
const BEZIER_SPLINE_SIZE = 11; // 样本点数量，用于预计算优化
const BEZIER_SAMPLE_STEP = 1.0 / (BEZIER_SPLINE_SIZE - 1.0); // 样本步长

/**
 * 贝塞尔曲线系数A
 * 三次贝塞尔曲线的三次项系数
 */
function getBezierCoefficientA(x1: number, x2: number): number {
	return 1.0 - 3.0 * x2 + 3.0 * x1;
}

/**
 * 贝塞尔曲线系数B
 * 三次贝塞尔曲线的二次项系数
 */
function getBezierCoefficientB(x1: number, x2: number): number {
	return 3.0 * x2 - 6.0 * x1;
}

/**
 * 贝塞尔曲线系数C
 * 三次贝塞尔曲线的一次项系数
 */
function getBezierCoefficientC(x1: number): number {
	return 3.0 * x1;
}

/**
 * 计算贝塞尔曲线值
 */
function calculateBezierValue(t: number, x1: number, x2: number): number {
	const a = getBezierCoefficientA(x1, x2);
	const b = getBezierCoefficientB(x1, x2);
	const c = getBezierCoefficientC(x1);
	return ((a * t + b) * t + c) * t;
}

/**
 * 计算贝塞尔曲线斜率
 */
function getBezierSlope(t: number, x1: number, x2: number): number {
	const a = getBezierCoefficientA(x1, x2);
	const b = getBezierCoefficientB(x1, x2);
	const c = getBezierCoefficientC(x1);
	return 3.0 * a * t * t + 2.0 * b * t + c;
}

/**
 * 二分法求解贝塞尔曲线参数
 */
function binarySearchBezierT(
	targetX: number,
	startT: number,
	endT: number,
	x1: number,
	x2: number
): number {
	let currentX: number;
	let currentT: number;
	let iterations = 0;
	const maxIterations = 10;
	const precision = 0.0000001;

	do {
		currentT = startT + (endT - startT) / 2.0;
		currentX = calculateBezierValue(currentT, x1, x2) - targetX;
		if (currentX > 0.0) {
			endT = currentT;
		} else {
			startT = currentT;
		}
		iterations++;
	} while (Math.abs(currentX) > precision && iterations < maxIterations);

	return currentT;
}

/**
 * 牛顿-拉夫逊法求解贝塞尔曲线参数
 */
function newtonRaphsonBezierT(
	targetX: number,
	initialGuess: number,
	x1: number,
	x2: number
): number {
	let t = initialGuess;
	const maxIterations = 4;

	for (let i = 0; i < maxIterations; i++) {
		const slope = getBezierSlope(t, x1, x2);
		if (slope == 0.0) {
			return t;
		}
		const currentX = calculateBezierValue(t, x1, x2) - targetX;
		t = t - currentX / slope;
	}
	return t;
}

/**
 * 创建贝塞尔缓动函数
 */
function createBezierEasing(x1: number, y1: number, x2: number, y2: number): EasingFunction | null {
	if (!(0 <= x1 && x1 <= 1 && 0 <= x2 && x2 <= 1)) {
		return null;
	}

	const sampleValues: number[] = [];
	if (x1 != y1 || x2 != y2) {
		for (let i = 0; i < BEZIER_SPLINE_SIZE; i++) {
			sampleValues.push(calculateBezierValue(i * BEZIER_SAMPLE_STEP, x1, x2));
		}
	}

	function getTParameterForX(x: number): number {
		let intervalStart = 0.0;
		let currentSample = 1;
		const lastSample = BEZIER_SPLINE_SIZE - 1;

		for (; currentSample != lastSample && sampleValues[currentSample] <= x; currentSample++) {
			intervalStart += BEZIER_SAMPLE_STEP;
		}
		currentSample--;

		const dist =
			(x - sampleValues[currentSample]) /
			(sampleValues[currentSample + 1] - sampleValues[currentSample]);
		const initialGuess = intervalStart + dist * BEZIER_SAMPLE_STEP;
		const initialSlope = getBezierSlope(initialGuess, x1, x2);

		if (initialSlope >= 0.001) {
			return newtonRaphsonBezierT(x, initialGuess, x1, x2);
		} else if (initialSlope == 0.0) {
			return initialGuess;
		}
		return binarySearchBezierT(x, intervalStart, intervalStart + BEZIER_SAMPLE_STEP, x1, x2);
	}

	return function (progress: number): number {
		if (x1 == y1 && x2 == y2) {
			return progress;
		}
		if (progress == 0.0 || progress == 1.0) {
			return progress;
		}
		return calculateBezierValue(getTParameterForX(progress), y1, y2);
	};
}

/**
 * 颜色工具函数：标准化颜色值格式
 */
function getDefaultColor(colorValue: string): string {
	if (colorValue.startsWith("#")) {
		return colorValue;
	}
	if (colorValue.startsWith("rgb")) {
		return colorValue;
	}
	return "#000000";
}

/**
 * 十六进制颜色转RGB对象
 */
function hexToRgb(hex: string): UTSJSONObject {
	const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
	if (result != null) {
		return {
			r: parseInt(result[1] ?? "0", 16),
			g: parseInt(result[2] ?? "0", 16),
			b: parseInt(result[3] ?? "0", 16),
			a: 1.0
		} as UTSJSONObject;
	}
	return {
		r: 0,
		g: 0,
		b: 0,
		a: 1.0
	} as UTSJSONObject;
}

/**
 * 高性能动画引擎类
 */
export class AnimationEngine {
	/** 预定义缓动函数映射 */
	private readonly easingPresets = new Map<string, number[]>([
		["linear", [0.0, 0.0, 1.0, 1.0]],
		["ease", [0.25, 0.1, 0.25, 1.0]],
		["easeIn", [0.42, 0.0, 1.0, 1.0]],
		["easeOut", [0.0, 0.0, 0.58, 1.0]],
		["easeInOut", [0.42, 0.0, 0.58, 1.0]],
		["easeInQuad", [0.55, 0.085, 0.68, 0.53]],
		["easeOutQuad", [0.25, 0.46, 0.45, 0.94]],
		["easeInOutQuad", [0.455, 0.03, 0.515, 0.955]],
		["easeInCubic", [0.55, 0.055, 0.675, 0.19]],
		["easeOutCubic", [0.215, 0.61, 0.355, 1.0]],
		["easeInOutCubic", [0.645, 0.045, 0.355, 1.0]],
		["easeInQuart", [0.895, 0.03, 0.685, 0.22]],
		["easeOutQuart", [0.165, 0.84, 0.44, 1.0]],
		["easeInOutQuart", [0.77, 0.0, 0.175, 1.0]],
		["easeInQuint", [0.755, 0.05, 0.855, 0.06]],
		["easeOutQuint", [0.23, 1.0, 0.32, 1.0]],
		["easeInOutQuint", [0.86, 0.0, 0.07, 1.0]],
		["easeInSine", [0.47, 0.0, 0.745, 0.715]],
		["easeOutSine", [0.39, 0.575, 0.565, 1.0]],
		["easeInOutSine", [0.445, 0.05, 0.55, 0.95]],
		["easeInExpo", [0.95, 0.05, 0.795, 0.035]],
		["easeOutExpo", [0.19, 1.0, 0.22, 1.0]],
		["easeInOutExpo", [1.0, 0.0, 0.0, 1.0]],
		["easeInCirc", [0.6, 0.04, 0.98, 0.335]],
		["easeOutCirc", [0.075, 0.82, 0.165, 1.0]],
		["easeInOutBack", [0.68, -0.55, 0.265, 1.55]]
	]);

	/** 目标DOM元素 */
	private targetElement: UniElement | null = null;

	/** 动画持续时间(毫秒) */
	private animationDuration: number = 500;

	/** 动画是否正在运行 */
	private isRunning: boolean = false;

	/** 动画是否暂停 */
	private isPaused: boolean = false;

	/** 当前动画进度 (0-1) */
	private currentProgress: number = 0;

	/** 是否反向播放 */
	private isReversed: boolean = false;

	/** 是否往返播放模式 */
	private isAlternate: boolean = false;
	/** 往返播放时是否处于反向状态 */
	private isAlternateReversed: boolean = false;

	/** 循环播放次数 (-1为无限循环) */
	private loopCount: number = 1;
	/** 当前已完成的循环次数 */
	private currentLoop: number = 0;

	/** 动画是否正在停止 */
	private isStopping: boolean = true;

	/** 当前执行的属性索引(顺序执行模式) */
	private currentAttributeIndex: number = 0;

	/** 回调函数 */
	private onComplete: () => void = () => {};
	private onStart: () => void = () => {};
	private onFrame: (progress: number) => void = () => {};

	/** 动画属性列表 */
	private animationAttributes: AnimationAttribute[] = [];

	/** 动画开始时间戳 */
	private startTimestamp: number = 0;

	/** 当前使用的缓动函数 */
	private currentEasingFunction: EasingFunction | null = null;

	/** 是否按属性顺序依次执行动画 */
	private isSequentialMode: boolean = false;

	// 平台相关的动画控制器
	// #ifdef APP-ANDROID
	private choreographer: Choreographer | null = null; // Android系统帧同步器
	private frameCallback: FrameCallback | null = null; // 帧回调处理器
	// #endif

	// iOS/小程序平台使用定时器
	// #ifdef APP-IOS
	private displayLinkTimer: number = 0; // iOS定时器ID
	// #endif

	// Web平台使用requestAnimationFrame
	private animationFrameId: number | null = null; // 动画帧ID

	/**
	 * 创建动画引擎实例
	 */
	constructor(element: UniElement | null, options: AnimationOptions) {
		this.targetElement = element;

		this.animationDuration =
			options.duration != null ? options.duration : this.animationDuration;
		this.loopCount = options.loop != null ? options.loop : this.loopCount;
		this.isAlternate = options.alternate != null ? options.alternate : this.isAlternate;
		this.isSequentialMode =
			options.sequential != null ? options.sequential : this.isSequentialMode;

		if (options.timingFunction != null) {
			const easingParams = this.easingPresets.get(options.timingFunction);
			if (easingParams != null) {
				this.currentEasingFunction = createBezierEasing(
					easingParams[0],
					easingParams[1],
					easingParams[2],
					easingParams[3]
				);
			}
		}

		if (options.bezier != null && options.bezier.length == 4) {
			this.currentEasingFunction = createBezierEasing(
				options.bezier[0],
				options.bezier[1],
				options.bezier[2],
				options.bezier[3]
			);
		}

		if (options.complete != null) {
			this.onComplete = options.complete;
		}
		if (options.start != null) {
			this.onStart = options.start;
		}
		if (options.frame != null) {
			this.onFrame = options.frame;
		}
	}

	/**
	 * 从样式值中提取单位
	 */
	private extractUnit(value?: string, propertyName?: string): string {
		if (value == null) return "px";
		const unit = value.replace(/[\d|\-|\+|\.]/g, "");

		if (propertyName == "opacity" || propertyName == "z-index") {
			return "";
		}

		return unit == "" ? "px" : unit;
	}

	/**
	 * 添加自定义缓动函数
	 */
	addCustomEasing(name: string, bezierParams: number[]): AnimationEngine {
		if (bezierParams.length == 4) {
			this.easingPresets.set(name, bezierParams);
		}
		return this;
	}

	/**
	 * 设置动画反向播放
	 */
	setReverse(reverse: boolean | null = null): AnimationEngine {
		if (reverse != null) {
			this.isReversed = reverse;
		} else {
			this.isReversed = !this.isReversed;
		}
		return this;
	}

	/**
	 * 设置循环播放次数
	 */
	setLoopCount(count: number): AnimationEngine {
		this.loopCount = count;
		return this;
	}

	/**
	 * 设置动画持续时间
	 */
	setDuration(duration: number): AnimationEngine {
		this.animationDuration = duration;
		return this;
	}

	/**
	 * 设置往返播放模式
	 */
	setAlternate(alternate: boolean): AnimationEngine {
		this.isAlternate = alternate;
		return this;
	}

	/**
	 * 设置顺序执行模式
	 */
	setSequential(sequential: boolean): AnimationEngine {
		this.isSequentialMode = sequential;
		return this;
	}

	/**
	 * 添加动画属性
	 */
	addAttribute(
		propertyName: string,
		fromValue: string,
		toValue: string,
		unique: boolean = true
	): AnimationEngine {
		const isColor = this.isColorProperty(propertyName);
		const unit = isColor ? "" : this.extractUnit(fromValue, propertyName);

		const processedFromValue = isColor
			? getDefaultColor(fromValue)
			: parseFloat(fromValue).toString();
		const processedToValue = isColor
			? getDefaultColor(toValue)
			: parseFloat(toValue).toString();

		let existingIndex = this.animationAttributes.findIndex(
			(attr: AnimationAttribute): boolean => attr.propertyName == propertyName
		);

		if (!unique) {
			existingIndex = -1;
		}

		const newAttribute: AnimationAttribute = {
			fromValue: processedFromValue,
			toValue: processedToValue,
			unit: unit,
			progress: 0,
			currentValue: processedFromValue,
			propertyName: propertyName
		};

		if (existingIndex == -1) {
			this.animationAttributes.push(newAttribute);
		} else {
			this.animationAttributes[existingIndex] = newAttribute;
		}

		return this;
	}

	/**
	 * 快捷方法：添加变换属性
	 */
	transform(property: string, fromValue: string, toValue: string): AnimationEngine {
		return this.addAttribute(property, fromValue, toValue);
	}

	/**
	 * 快捷方法：添加位移动画
	 */
	translate(fromX: string, fromY: string, toX: string, toY: string): AnimationEngine {
		this.addAttribute("translateX", fromX, toX);
		this.addAttribute("translateY", fromY, toY);
		return this;
	}

	/**
	 * 添加X轴位移动画
	 */
	translateX(fromX: string, toX: string): AnimationEngine {
		return this.addAttribute("translateX", fromX, toX);
	}

	/**
	 * 添加Y轴位移动画
	 */
	translateY(fromY: string, toY: string): AnimationEngine {
		return this.addAttribute("translateY", fromY, toY);
	}

	/**
	 * 快捷方法：添加缩放动画
	 */
	scale(fromScale: string, toScale: string): AnimationEngine {
		return this.addAttribute("scale", fromScale, toScale);
	}

	/**
	 * 快捷方法：添加旋转动画
	 */
	rotate(fromDegree: string, toDegree: string): AnimationEngine {
		return this.addAttribute("rotate", fromDegree, toDegree);
	}

	/**
	 * 快捷方法：添加透明度动画
	 */
	opacity(fromOpacity: string, toOpacity: string): AnimationEngine {
		return this.addAttribute("opacity", fromOpacity, toOpacity);
	}

	/**
	 * 线性插值计算
	 */
	private interpolateValue(startValue: number, endValue: number, progress: number): number {
		return startValue + (endValue - startValue) * progress;
	}

	/**
	 * 判断是否为颜色相关属性（核心修复：显式返回boolean，避免类型歧义）
	 */
	private isColorProperty(propertyName: string): boolean {
		// 直接用基础条件判断，避免数组方法导致的类型推导问题
		return (
			propertyName.indexOf("background") > -1 ||
			propertyName.indexOf("color") > -1 ||
			propertyName.indexOf("border-color") > -1 ||
			propertyName.indexOf("shadow") > -1
		);
	}

	/**
	 * 判断是否为Transform相关属性（核心修复：显式返回boolean，避免类型歧义）
	 */
	private isTransformProperty(propertyName: string): boolean {
		// 直接用===判断，避免数组方法导致的类型推导问题
		return (
			propertyName === "scaleX" ||
			propertyName === "scaleY" ||
			propertyName === "scale" ||
			propertyName === "rotateX" ||
			propertyName === "rotateY" ||
			propertyName === "rotate" ||
			propertyName === "translateX" ||
			propertyName === "translateY" ||
			propertyName === "translate"
		);
	}

	/**
	 * 设置元素样式属性（核心修复：颜色取值时显式类型断言+默认值，消除Any?）
	 */
	private setElementProperty(
		propertyName: string,
		currentValue: number,
		unit: string,
		progress: number,
		attribute: AnimationAttribute
	): void {
		if (this.targetElement == null) return;

		const element = this.targetElement;
		const valueStr = currentValue.toFixed(2);

		// #ifdef MP
		if (element.style == null) {
			return;
		}
		// #endif

		switch (propertyName) {
			case "scaleX":
				element.style!.setProperty("transform", `scaleX(${currentValue})`);
				break;
			case "scaleY":
				element.style!.setProperty("transform", `scaleY(${currentValue})`);
				break;
			case "scale":
				element.style!.setProperty("transform", `scale(${currentValue})`);
				break;
			case "rotateX":
				element.style!.setProperty("transform", `rotateX(${valueStr + unit})`);
				break;
			case "rotateY":
				element.style!.setProperty("transform", `rotateY(${valueStr + unit})`);
				break;
			case "rotate":
				element.style!.setProperty("transform", `rotate(${valueStr + unit})`);
				break;
			case "translateX":
				element.style!.setProperty("transform", `translateX(${valueStr + unit})`);
				break;
			case "translateY":
				element.style!.setProperty("transform", `translateY(${valueStr + unit})`);
				break;
			case "translate":
				element.style!.setProperty(
					"transform",
					`translate(${valueStr + unit},${valueStr + unit})`
				);
				break;
			default:
				if (this.isColorProperty(propertyName)) {
					const startColor = hexToRgb(attribute.fromValue);
					const endColor = hexToRgb(attribute.toValue);

					// 核心修复：显式断言为number，并设置默认值，避免Any?类型
					const startR = (startColor["r"] as number) ?? 0;
					const startG = (startColor["g"] as number) ?? 0;
					const startB = (startColor["b"] as number) ?? 0;
					const startA = (startColor["a"] as number) ?? 1.0;

					const endR = (endColor["r"] as number) ?? 0;
					const endG = (endColor["g"] as number) ?? 0;
					const endB = (endColor["b"] as number) ?? 0;
					const endA = (endColor["a"] as number) ?? 1.0;

					const r = this.interpolateValue(startR, endR, progress);
					const g = this.interpolateValue(startG, endG, progress);
					const b = this.interpolateValue(startB, endB, progress);
					const a = this.interpolateValue(startA, endA, progress);

					element.style!.setProperty(
						propertyName,
						`rgba(${r.toFixed(0)},${g.toFixed(0)},${b.toFixed(0)},${a.toFixed(1)})`
					);
				} else {
					element.style!.setProperty(propertyName, valueStr + unit);
				}
				break;
		}
	}

	/**
	 * Web平台动画运行方法 (H5/iOS/Harmony)
	 */
	private runWebAnimation(): void {
		// #ifdef H5 || APP-IOS || APP-HARMONY
		const self = this;
		self.startTimestamp = 0;

		if (self.animationFrameId != null) {
			cancelAnimationFrame(self.animationFrameId);
		}

		function animationLoop(): void {
			if (self.startTimestamp <= 0) {
				self.startTimestamp = Date.now();
			}

			const elapsed = Date.now() - self.startTimestamp;
			const progress = Math.min(elapsed / self.animationDuration + self.currentProgress, 1.0);

			self.updateAnimationFrame(progress);

			if (self.isPaused) {
				self.isRunning = false;
				self.currentProgress = progress;
				return;
			}

			if (progress >= 1.0 || self.isStopping) {
				self.handleAnimationComplete();
				return;
			}

			if (progress < 1.0 && self.isRunning) {
				self.onFrame(progress);
				self.animationFrameId = requestAnimationFrame(animationLoop);
			}
		}

		self.onStart();
		animationLoop();
		// #endif
	}

	/**
	 * 更新动画帧
	 */
	private updateAnimationFrame(progress: number): void {
		if (this.targetElement == null) return;

		if (!this.isSequentialMode) {
			for (let i = 0; i < this.animationAttributes.length; i++) {
				this.updateSingleAttribute(this.animationAttributes[i], progress);
			}
		} else {
			if (this.currentAttributeIndex < this.animationAttributes.length) {
				this.updateSingleAttribute(
					this.animationAttributes[this.currentAttributeIndex],
					progress
				);
			}
		}
	}

	/**
	 * 更新单个属性的动画
	 */
	private updateSingleAttribute(attribute: AnimationAttribute, progress: number): void {
		attribute.progress = progress;

		if (!this.isColorProperty(attribute.propertyName)) {
			const fromValue = parseFloat(attribute.fromValue);
			const toValue = parseFloat(attribute.toValue);

			let easedProgress = progress;
			if (this.currentEasingFunction != null) {
				easedProgress = this.currentEasingFunction(progress);
			}

			let currentValue = this.interpolateValue(fromValue, toValue, easedProgress);

			if (this.isReversed || this.isAlternateReversed) {
				currentValue = this.interpolateValue(toValue, fromValue, easedProgress);
			}

			this.setElementProperty(
				attribute.propertyName,
				currentValue,
				attribute.unit,
				progress,
				attribute
			);
		} else {
			this.setElementProperty(attribute.propertyName, 0, attribute.unit, progress, attribute);
		}
	}

	/**
	 * 处理动画完成
	 */
	private handleAnimationComplete(): void {
		if (
			this.isSequentialMode &&
			this.currentAttributeIndex < this.animationAttributes.length - 1
		) {
			this.currentAttributeIndex++;
			this.currentProgress = 0;
			this.restartAnimation();
			return;
		}

		// #ifdef H5 || APP-IOS || APP-HARMONY
		if (this.animationFrameId != null) {
			cancelAnimationFrame(this.animationFrameId);
		}
		// #endif

		this.currentAttributeIndex = 0;
		this.currentProgress = 0;

		if (this.isAlternate) {
			this.isAlternateReversed = !this.isAlternateReversed;
		}

		if (this.loopCount == -1) {
			this.restartAnimation();
			return;
		} else {
			this.currentLoop++;
			if (this.currentLoop < this.loopCount) {
				this.restartAnimation();
				return;
			}
		}

		this.isRunning = false;
		this.onComplete();
	}

	/**
	 * 根据平台重新启动动画
	 */
	private restartAnimation(): void {
		this.startTimestamp = 0;

		// #ifdef H5 || APP-IOS || APP-HARMONY
		this.runWebAnimation();
		// #endif
		// #ifdef APP-ANDROID
		this.runAndroidAnimation();
		// #endif
		// #ifdef MP
		this.runMPAnimation();
		// #endif
	}

	/**
	 * Android平台动画运行方法
	 */
	private runAndroidAnimation(): void {
		// #ifdef APP-ANDROID
		const self = this;
		self.startTimestamp = 0;

		let choreographer = self.choreographer;
		if (choreographer == null) {
			choreographer = Choreographer.getInstance();
			self.choreographer = choreographer;
		} else {
			if (self.frameCallback != null) {
				choreographer.removeFrameCallback(self.frameCallback);
			}
		}

		/**
		 * Android原生帧回调类
		 */
		class frameCallback extends Choreographer.FrameCallback {
			// @ts-ignore
			override doFrame(frameTimeNanos: Long) {
				if (!self.isRunning || self.isStopping) {
					return;
				}

				if (self.startTimestamp <= 0) {
					self.startTimestamp = Date.now();
				}

				const elapsed = Date.now() - self.startTimestamp;
				const progress = Math.min(
					elapsed / self.animationDuration + self.currentProgress,
					1.0
				);

				self.updateAnimationFrame(progress);

				if (self.isPaused) {
					self.isRunning = false;
					self.currentProgress = progress;
					return;
				}

				if (progress >= 1.0 || self.isStopping) {
					self.handleAnimationComplete();
					return;
				}

				if (progress < 1.0 && self.isRunning && !self.isStopping) {
					self.onFrame(progress);
					const currentChoreographer = self.choreographer;
					if (currentChoreographer != null) {
						currentChoreographer.postFrameCallback(this);
					}
				}
			}
		}

		self.onStart();
		self.frameCallback = new frameCallback();
		if (choreographer != null) {
			choreographer.postFrameCallback(self.frameCallback);
		}
		// #endif
	}

	/**
	 * 小程序平台动画运行方法
	 */
	private runMPAnimation(): void {
		// #ifdef MP
		const self = this;
		self.startTimestamp = 0;

		if (self.displayLinkTimer != 0) {
			clearTimeout(self.displayLinkTimer);
		}

		function animationLoop(): void {
			if (self.startTimestamp <= 0) {
				self.startTimestamp = Date.now();
			}

			const elapsed = Date.now() - self.startTimestamp;
			const progress = Math.min(elapsed / self.animationDuration + self.currentProgress, 1.0);

			self.updateAnimationFrame(progress);

			if (self.isPaused) {
				self.isRunning = false;
				self.currentProgress = progress;
				return;
			}

			if (progress >= 1.0 || self.isStopping) {
				self.handleAnimationComplete();
				return;
			}

			if (progress < 1.0 && self.isRunning) {
				self.onFrame(progress);
				self.displayLinkTimer = setTimeout(animationLoop, 16) as any;
			}
		}

		self.onStart();
		animationLoop();
		// #endif
	}

	/**
	 * 开始播放动画
	 */
	play(): AnimationEngine {
		if (this.isRunning) return this;

		this.isRunning = true;
		this.isStopping = false;
		this.isPaused = false;
		this.currentLoop = 0;
		this.currentAttributeIndex = 0;

		// #ifdef H5 || APP-IOS || APP-HARMONY
		this.runWebAnimation();
		// #endif
		// #ifdef APP-ANDROID
		this.runAndroidAnimation();
		// #endif
		// #ifdef MP
		this.runMPAnimation();
		// #endif

		return this;
	}

	/**
	 * 异步播放动画，支持await
	 */
	playAsync(): Promise<void> {
		return new Promise<void>((resolve) => {
			const originalComplete = this.onComplete;
			this.onComplete = () => {
				originalComplete();
				resolve();
			};
			this.play();
		});
	}

	/**
	 * 停止动画
	 */
	stop(): AnimationEngine {
		this.isStopping = true;
		this.currentProgress = 0;
		this.currentAttributeIndex = this.animationAttributes.length;

		// #ifdef WEB || APP-IOS || APP-HARMONY
		if (this.animationFrameId != null) {
			cancelAnimationFrame(this.animationFrameId);
			this.animationFrameId = null;
		}
		// #endif

		// #ifdef APP-ANDROID
		const choreographer = this.choreographer;
		const frameCallback = this.frameCallback;
		if (choreographer != null && frameCallback != null) {
			choreographer.removeFrameCallback(frameCallback);
		}
		// #endif

		// #ifdef MP
		if (this.displayLinkTimer != 0) {
			clearTimeout(this.displayLinkTimer);
			this.displayLinkTimer = 0;
		}
		// #endif

		this.isRunning = false;
		return this;
	}

	/**
	 * 暂停动画
	 */
	pause(): AnimationEngine {
		this.isPaused = true;
		return this;
	}

	/**
	 * 恢复暂停的动画
	 */
	resume(): AnimationEngine {
		if (this.isPaused) {
			this.isPaused = false;
			this.play();
		}
		return this;
	}

	/**
	 * 清空应用到元素上的动画样式
	 */
	private clearElementStyles(): void {
		if (this.targetElement == null) return;

		const element = this.targetElement;

		for (const attr of this.animationAttributes) {
			const propertyName = attr.propertyName;

			if (this.isTransformProperty(propertyName)) {
				element.style!.setProperty("transform", "");
			} else {
				element.style!.setProperty(propertyName, "");
			}
		}
	}

	/**
	 * 重置动画到初始状态
	 */
	reset(): AnimationEngine {
		this.stop();

		this.clearElementStyles();

		this.currentProgress = 0;
		this.currentLoop = 0;
		this.currentAttributeIndex = 0;
		this.isAlternateReversed = false;
		this.isReversed = false;
		this.isPaused = false;
		this.isStopping = true;
		this.startTimestamp = 0;

		this.animationAttributes = [];

		this.currentEasingFunction = null;

		this.onComplete = () => {};
		this.onStart = () => {};
		this.onFrame = () => {};

		// #ifdef WEB || APP-IOS || APP-HARMONY
		if (this.animationFrameId != null) {
			cancelAnimationFrame(this.animationFrameId);
			this.animationFrameId = null;
		}
		// #endif

		// #ifdef APP-ANDROID
		const choreographer = this.choreographer;
		const frameCallback = this.frameCallback;
		if (choreographer != null && frameCallback != null) {
			choreographer.removeFrameCallback(frameCallback);
			this.frameCallback = null;
		}
		this.choreographer = null;
		// #endif

		// #ifdef MP
		if (this.displayLinkTimer != 0) {
			clearTimeout(this.displayLinkTimer);
			this.displayLinkTimer = 0;
		}
		// #endif

		return this;
	}

	/**
	 * 获取当前动画进度
	 */
	getProgress(): number {
		return this.currentProgress;
	}

	/**
	 * 获取动画是否正在运行
	 */
	isAnimating(): boolean {
		return this.isRunning;
	}

	/**
	 * 获取当前循环次数
	 */
	getCurrentLoop(): number {
		return this.currentLoop;
	}

	/**
	 * 清除所有动画属性
	 */
	clearAttributes(): AnimationEngine {
		this.animationAttributes = [];
		return this;
	}

	/**
	 * 获取动画属性数量
	 */
	getAttributeCount(): number {
		return this.animationAttributes.length;
	}

	/**
	 * 淡入动画
	 */
	fadeIn(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).opacity("0", "1");
	}

	/**
	 * 淡出动画
	 */
	fadeOut(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).opacity("1", "0");
	}

	/**
	 * 滑入动画(从左)
	 */
	slideInLeft(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).translateX("-100%", "0%").opacity("0", "1");
	}

	/**
	 * 滑入动画(从右)
	 */
	slideInRight(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).translateX("100%", "0%").opacity("0", "1");
	}

	/**
	 * 滑入动画(从上)
	 */
	slideInUp(duration: number = 300): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("translateY", "-100%", "0%")
			.opacity("0", "1");
	}

	/**
	 * 滑入动画(从下)
	 */
	slideInDown(duration: number = 300): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("translateY", "100%", "0%")
			.opacity("0", "1");
	}

	/**
	 * 缩放动画(放大)
	 */
	zoomIn(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).scale("0", "1").opacity("0", "1");
	}

	/**
	 * 缩放动画(缩小)
	 */
	zoomOut(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).scale("1", "0").opacity("1", "0");
	}

	/**
	 * 旋转动画
	 */
	rotateIn(duration: number = 500, degrees: number = 360): AnimationEngine {
		return this.setDuration(duration).rotate("0deg", `${degrees}deg`).opacity("0", "1");
	}

	/**
	 * 旋转退出动画
	 */
	rotateOut(duration: number = 500, degrees: number = 360): AnimationEngine {
		return this.setDuration(duration).rotate("0deg", `${degrees}deg`).opacity("1", "0");
	}

	/**
	 * 弹跳动画
	 */
	bounce(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.addCustomEasing("bounce", [0.68, -0.55, 0.265, 1.55])
			.scale("1", "1.1")
			.setAlternate(true)
			.setLoopCount(2);
	}

	/**
	 * 摇摆动画
	 */
	shake(duration: number = 500): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("translateX", "0px", "10px")
			.setAlternate(true)
			.setLoopCount(6);
	}

	/**
	 * 链式动画：支持多个动画依次执行
	 */
	sequence(animations: ((engine: AnimationEngine) => AnimationEngine)[]): AnimationEngine {
		const self = this;

		if (animations.length == 0) {
			return this;
		}

		const firstEngine = animations[0](new AnimationEngine(this.targetElement, {}));

		if (animations.length == 1) {
			return firstEngine;
		}

		function setNextAnimation(
			currentEngine: AnimationEngine,
			remainingAnimations: ((engine: AnimationEngine) => AnimationEngine)[]
		): void {
			if (remainingAnimations.length == 0) {
				return;
			}

			const originalComplete = currentEngine.onComplete;
			currentEngine.onComplete = () => {
				originalComplete();

				const nextEngine = remainingAnimations[0](
					new AnimationEngine(self.targetElement, {})
				);

				if (remainingAnimations.length > 1) {
					setNextAnimation(nextEngine, remainingAnimations.slice(1));
				}

				nextEngine.play();
			};
		}

		setNextAnimation(firstEngine, animations.slice(1));

		return firstEngine;
	}

	/**
	 * 滑出动画(向左)
	 */
	slideOutLeft(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).translateX("0%", "-100%").opacity("1", "0");
	}

	/**
	 * 滑出动画(向右)
	 */
	slideOutRight(duration: number = 300): AnimationEngine {
		return this.setDuration(duration).translateX("0%", "100%").opacity("1", "0");
	}

	/**
	 * 滑出动画(向上)
	 */
	slideOutUp(duration: number = 300): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("translateY", "0%", "-100%")
			.opacity("1", "0");
	}

	/**
	 * 滑出动画(向下)
	 */
	slideOutDown(duration: number = 300): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("translateY", "0%", "100%")
			.opacity("1", "0");
	}

	/**
	 * 翻转动画(水平)
	 */
	flipX(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("rotateX", "0deg", "180deg")
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 翻转动画(垂直)
	 */
	flipY(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("rotateY", "0deg", "180deg")
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 弹性进入动画
	 */
	elasticIn(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.scale("0", "1")
			.opacity("0", "1")
			.addCustomEasing("elastic", [0.175, 0.885, 0.32, 1.275]);
	}

	/**
	 * 弹性退出动画
	 */
	elasticOut(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.scale("1", "0")
			.opacity("1", "0")
			.addCustomEasing("elastic", [0.68, -0.55, 0.265, 1.55]);
	}

	/**
	 * 回弹动画
	 */
	rubberBand(duration: number = 1000): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("scaleX", "1", "1.25")
			.addAttribute("scaleY", "1", "0.75")
			.setAlternate(true)
			.setLoopCount(2)
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 摆动动画
	 */
	swing(duration: number = 1000): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("rotate", "0deg", "15deg")
			.setAlternate(true)
			.setLoopCount(4)
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 抖动动画
	 */
	wobble(duration: number = 1000): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("translateX", "0px", "25px")
			.addAttribute("rotate", "0deg", "5deg")
			.setAlternate(true)
			.setLoopCount(4);
	}

	/**
	 * 滚动进入动画
	 */
	rollIn(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.translateX("-100%", "0%")
			.rotate("-120deg", "0deg")
			.opacity("0", "1");
	}

	/**
	 * 滚动退出动画
	 */
	rollOut(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.translateX("0%", "100%")
			.rotate("0deg", "120deg")
			.opacity("1", "0");
	}

	/**
	 * 灯光效果动画
	 */
	lightSpeed(duration: number = 500): AnimationEngine {
		return this.setDuration(duration)
			.translateX("-100%", "0%")
			.addAttribute("skewX", "-30deg", "0deg")
			.opacity("0", "1")
			.addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
	}

	/**
	 * 浮动动画
	 */
	float(duration: number = 3000): AnimationEngine {
		return this.setDuration(duration)
			.translateY("0px", "-10px")
			.setAlternate(true)
			.setLoopCount(-1)
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 呼吸动画
	 */
	breathe(duration: number = 2000): AnimationEngine {
		return this.setDuration(duration)
			.scale("1", "1.1")
			.setAlternate(true)
			.setLoopCount(-1)
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 发光动画
	 */
	glow(duration: number = 1500): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute(
				"boxShadow",
				"0 0 5px rgba(255,255,255,0.5)",
				"0 0 20px rgba(255,255,255,1)"
			)
			.setAlternate(true)
			.setLoopCount(-1)
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 进度条动画
	 */
	progressBar(duration: number = 1000, progress: number = 100): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("width", "0%", `${progress}%`)
			.addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
	}

	/**
	 * 模态框进入动画
	 */
	modalIn(duration: number = 300): AnimationEngine {
		return this.setDuration(duration)
			.scale("0.7", "1")
			.opacity("0", "1")
			.addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
	}

	/**
	 * 模态框退出动画
	 */
	modalOut(duration: number = 300): AnimationEngine {
		return this.setDuration(duration)
			.scale("1", "0.7")
			.opacity("1", "0")
			.addCustomEasing("ease-in", [0.42, 0.0, 1.0, 1.0]);
	}

	/**
	 * 卡片翻转动画
	 */
	cardFlip(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.addAttribute("rotateY", "0deg", "180deg")
			.addCustomEasing("ease-in-out", [0.25, 0.1, 0.25, 1.0]);
	}

	/**
	 * 波纹扩散动画
	 */
	ripple(duration: number = 600): AnimationEngine {
		return this.setDuration(duration)
			.scale("0", "4")
			.opacity("0.7", "0")
			.addCustomEasing("ease-out", [0.25, 0.46, 0.45, 0.94]);
	}
}

/**
 * 创建动画实例
 */
export function createAnimation(
	element: UniElement | null,
	options: AnimationOptions = {}
): AnimationEngine {
	return new AnimationEngine(element, options);
}
